import json
import requests
import os
import tkinter as tk
from tkinter import filedialog
import colorama
from tqdm import tqdm as base_tqdm
from tqdm.contrib.concurrent import thread_map
import datetime
import sys
import concurrent.futures
import time
from tqdm import tqdm

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0'
}

test_v = int(0)
error_v = int(0)

class colors:
    HEADER = colorama.Fore.RESET
    BLUE = colorama.Fore.LIGHTCYAN_EX
    GREEN = colorama.Fore.LIGHTGREEN_EX
    WARNING = colorama.Fore.LIGHTYELLOW_EX
    FAIL = colorama.Fore.LIGHTRED_EX
    ENDC = colorama.Fore.RESET
    UNDERLINE = colorama.Fore.RESET
    RESET = colorama.Fore.RESET
    INOF = colorama.Fore.LIGHTWHITE_EX


def op(out, put):
    now = datetime.datetime.now()
    current_time = now.strftime("%H:%M:%S")
    if put == "1":
        print(colors.INOF + f"[Information：{current_time}] {out}" + colors.ENDC)
    elif put == "2":
        print(colors.GREEN + f"[Success：{current_time}] " + colors.ENDC + str(out))
    elif put == "3":
        print(colors.FAIL + f"[Error：{current_time}] " + colors.ENDC + str(out))
    elif put == "4":
        print(colors.WARNING + f"[WARNING：{current_time}] " + colors.ENDC + str(out))


def download_chunk(chunk_info):
    global test_v, error_v
    url, start_byte, end_byte, file_name, headers, chunk_num, total_chunks = chunk_info

    chunk_headers = headers.copy()
    chunk_headers['Range'] = f'bytes={start_byte}-{end_byte}'


    with base_tqdm(total=end_byte - start_byte + 1, unit='B', unit_scale=True, unit_divisor=1024,
                  desc=f"线程 {chunk_num}/{total_chunks}", position=chunk_num) as pbar:

        for attempt in range(10): 
            try:
                response = requests.get(url, headers=chunk_headers, verify=False, stream=True, timeout=10)
                if response.status_code == 206: 
                    with open(file_name, 'rb+') as f:
                        f.seek(start_byte)
                        for chunk in response.iter_content(chunk_size=1024):
                            if chunk:
                                f.write(chunk)
                                pbar.update(len(chunk))
                    return 
                else:
                    op(f"线程 {chunk_num}/{total_chunks} 下载失败: {response.status_code}, 正在重试 ({attempt + 1}/10)...", "3")
                    test_v = test_v + 1
                    time.sleep(2 ** attempt) 
            except requests.exceptions.RequestException as e:
                op(f"线程 {chunk_num}/{total_chunks} 下载出错: {e}, 正在重试 ({attempt + 1}/10)...", "3")
                time.sleep(2 ** attempt)  

        op(f"线程 {chunk_num}/{total_chunks} 下载失败，已达到最大重试次数", "3")
        error_v = error_v + 1


def download(url, save_path, file_name, num_threads=12):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
    }
    response = requests.head(url, headers=headers, verify=False)  

    if 'Content-Length' in response.headers:
        file_size = int(response.headers['Content-Length'])
    else:
        op("Content-Length header is not available. Using single-threaded download.", "4")
        return download_single_thread(url, save_path, file_name)  

    full_file_path = f"{save_path}\\\\{file_name}"

    
    with open(full_file_path, 'wb') as f:
        f.truncate(file_size)

   
    chunk_size = file_size // num_threads

    
    chunk_infos = [(url, i * chunk_size, (i + 1) * chunk_size - 1 if i < num_threads - 1 else file_size - 1,
                    full_file_path, headers, i + 1, num_threads) for i in range(num_threads)]

   
    thread_map(download_chunk, chunk_infos, max_workers=num_threads)

    op(f"下载完成, 文件保存位置: {full_file_path}", "2")

def download_single_thread(url, save_path, file_name):
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
    }
    response = requests.get(url, headers=headers, verify=False, stream=True)

    if 'Content-Length' in response.headers:
        file_size = int(response.headers['Content-Length']) / 1024
    else:
        op("Content-Length header is not available. Unable to display progress.", "4")
        file_size = None

    full_file_path = f"{save_path}\\\\{file_name}"

    with open(full_file_path, mode="wb") as f:
        if file_size:
            for data in tqdm(iterable=response.iter_content(1024), total=file_size, unit='k',
                             desc=f"正在下载文件...[{file_name}]"):
                f.write(data)
        else:
            for data in response.iter_content(1024):
                f.write(data)



def WGET_D(RUL, xcr, path, name):
    xcr = int(xcr)
    global pathx_pyinstaller
    op("请选择保存目录", "1")
    pathx_pyinstaller = f"{path}"

    op("正在获取直连下载地址...", "1")
    get_download_client = RUL  # RUL 现在应该已经是链接字符串了
    get_download_client_download = json.loads(requests.put(f"https://pan.huang1111.cn/api/v3/share/download/{get_download_client.split('/')[-1]}", headers=headers,verify=False).text)
    op("获取成功", "2")
    get_download_client_file_name = json.loads(requests.get(f"https://pan.huang1111.cn/api/v3/share/info/{get_download_client.split('/')[-1]}", headers=headers,verify=False).text)
    print(get_download_client_file_name," | ",f" {name}", "|", {get_download_client_download['data']})
    if os.path.isfile(f"{pathx_pyinstaller}\\{name}"):
        op("删除上次残留文件...", "1")
        os.remove(f"{pathx_pyinstaller}\\{name}")
    op("正在下载文件...", "1")
    start_time = time.time()
    
    download(f"{get_download_client_download['data']}", f"{pathx_pyinstaller}",f"{name}", num_threads=xcr)
    
    end_time = time.time()  # 记录结束时间
    global path_save, elapsed_time
    elapsed_time = end_time - start_time  # 计算耗时
    path_save = f"{pathx_pyinstaller}/{name}"








